// Andrew Davies.

#include "DXUT.h"
#include "DXUTgui.h"
#include "DXUTmisc.h"
#include "DXUTCamera.h"
#include "DXUTSettingsDlg.h"
#include "SDKmisc.h"
#include "SDKmesh.h"
#include "resource.h"
#include "misc.h"
#include "Physics/Engine/physicsEngine.h"
#include "Physics/Debug/physicsDebug.h"
#include "DevGraphics/devGraphics.h"
#include <iostream>
#include "tinyxml.h"
#include "Dav/dav.h"

// GET CLOSEST
//#include <vector>

#define EMPIRE_FORCE_LINE_SCALE ( 0.001f )

#define HARDCODED_SHAPES_ON 1

#if HARDCODED_SHAPES_ON
//#define EMPIRE_NUMBER_OF_SHAPES ( ( int )5 )
#define EMPIRE_NUMBER_OF_SHAPES ( ( int )3 )
#endif


bool g_bMouseLButtonDown = false;
bool g_bMouseRButtonDown = false;
bool g_bMouseMButtonDown = false;
short int g_nCurrentButtonMask = 0;
short int g_nMouseWheelDelta = 0;
POINT g_ptLastMousePosition;

#if HARDCODED_SHAPES_ON
unsigned int g_IntersectedShapeIndex = EMPIRE_NUMBER_OF_SHAPES;			
//unsigned int g_TranslationDragShapeIndex = EMPIRE_NUMBER_OF_SHAPES;
//unsigned int g_RotationDragShapeIndex = EMPIRE_NUMBER_OF_SHAPES;
#else
unsigned int g_IntersectedShapeIndex = PHYSICS_SHAPE_NULL_UID;	
#endif
bool g_bTranslationDrag = false;
bool g_bRotationDrag = false;
D3DXVECTOR4 g_oPreviousDragRayPosition( 0.0f, 0.0f, 0.0f, 1.0f );
D3DXVECTOR4 g_oPreviousDragRayDirection( 0.0f, 0.0f, 0.0f, 0.0f );

//Physics::VClipEnum g_VClipState = Physics::VClipContinue;

namespace Empire
{

Physics::EngineClass g_physicsEngine;
Physics::DebugClass g_physicsDebug;

Dav::SceneClass g_davScene;

#define EMPIRE_FOV ( D3DX_PI / 4 )
#define EMPIRE_NEAR_CLIP_PLANE ( 0.1f )
#define EMPIRE_FAR_CLIP_PLANE ( 1000.0f )
float g_aspectRatio = 1.0f;

D3DXVECTOR4 const g_accelerationDueToGravity( 0.0f, -9.8f, 0.0f, 0.0f );
bool g_applyGravity = true;

D3DXVECTOR4 const g_force0LocalSpace( 0.0f, -80.0f, 0.0f, 0.0f );
D3DXVECTOR4 const g_force0ApplicationPositionLocalSpace( -4.0f, 1.0f, 0.0, 1.0f );		

D3DXVECTOR4 const g_force1LocalSpace( 0.0f, -80.0f, 0.0f, 0.0f );
D3DXVECTOR4 const g_force1ApplicationPositionLocalSpace( 4.0f, 1.0f, 0.0, 1.0f );		

enum InputActionEnum
{
	gravityInputAction,
	force0InputAction,
	force1InputAction,

	outputStateInputAction,
	//vClipIterationInputAction,

	numberOfInputActions
};

InputActionEnum mapKeyToInputAction( UINT const nKey )
{
    switch( nKey )
    {
        case 'G': return gravityInputAction;
        case 'N': return force0InputAction;
        case 'M': return force1InputAction;
        case ' ': return outputStateInputAction;
        //case ' ': return vClipIterationInputAction;
    }

    return numberOfInputActions;
}

bool g_inputActionArray[ numberOfInputActions ];
bool g_previousInputActionArray[ numberOfInputActions ];

void initialise()
{
	g_physicsEngine.create();
	g_physicsDebug.create( g_physicsEngine );

	for( int inputAction = 0; inputAction != numberOfInputActions; ++inputAction )
	{
		g_inputActionArray[ inputAction ] = false;
		g_previousInputActionArray[ inputAction ] = false;
	}	

	//DevGraphics::line( 
	//	0, // int UID,
	//	D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromPosition,
	//	D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromColour,
	//	D3DXVECTOR4( 0.0f, 50.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & toPosition,
	//	D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & toColour,
	//	false, // bool infiniteLife,
	//	5.0f ); // float lifeTime );

	//DevGraphics::point( 
	//	0, // int UID,
	//	D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & position,
	//	12.0f, // size
	//	D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ), // D3DXVECTOR4 const & colour,
	//	true, // bool infiniteLife,
	//	5.0f ); // float lifeTime );

}

void shutdown()
{
	g_physicsDebug.destroy();
	g_physicsEngine.destroy();
}

}

//#define DEBUG_VS   // Uncomment this line to debug D3D9 vertex shaders 
//#define DEBUG_PS   // Uncomment this line to debug D3D9 pixel shaders 
#define FIRST_PERSON_CAMERA

//// A structure for our custom vertex type
//struct CUSTOMVERTEX
//{
//    FLOAT x, y, z; //, rhw; // The transformed position for the vertex
//    DWORD colour;        // The vertex colour
//};
//
//// Our custom FVF, which describes our custom vertex structure
//#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) // (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

#define FRAMES_PER_SECOND ( 60 )
#define SECONDS_PER_FRAME ( 1.0f / ( float )FRAMES_PER_SECOND )

#define METRES_PER_MILE ( 1609.344f )
#define MILES_PER_METRE ( 1.0f / METRES_PER_MILE )

#define SECONDS_PER_HOUR ( 60.0f * 60.0f )

#define MILES_PER_HOUR_TO_METRES_PER_SECOND( x )	( ( x ) * ( METRES_PER_MILE / SECONDS_PER_HOUR ) )

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
#if defined( FIRST_PERSON_CAMERA )
CFirstPersonCamera			g_Camera;
#else
CModelViewerCamera          g_Camera;               // A model viewing camera
#endif
CDXUTDialogResourceManager  g_DialogResourceManager; // manager for shared resources of dialogs
CD3DSettingsDlg             g_SettingsDlg;          // Device settings dialog
CDXUTTextHelper*            g_pTxtHelper = NULL;
CDXUTDialog                 g_HUD;                  // dialog for standard controls
CDXUTDialog                 g_SampleUI;             // dialog for sample specific controls

// Direct3D 9 resources
ID3DXFont*                  g_pFont9 = NULL;
ID3DXSprite*                g_pSprite9 = NULL;
ID3DXEffect*                g_pEffect9 = NULL;

#if HARDCODED_SHAPES_ON
unsigned int g_shapeUIDArray[ EMPIRE_NUMBER_OF_SHAPES ];
//Physics::ShapeClass g_shapeArray[ EMPIRE_NUMBER_OF_SHAPES ];
//Physics::FeatureClass g_featureArray[ EMPIRE_NUMBER_OF_SHAPES ];
//Physics::ShapeClass g_shape;
//typedef std::vector< Physics::ShapePairClass > ShapePairVectorClass;
//ShapePairVectorClass g_shapePairVector;

//bool g_shapeGravityApplied = false;
//bool g_shapeForce0Applied = false;
//bool g_shapeForce1Applied = false;

//Physics::ShapeClass g_floorShape;
#endif

#define EMPIRE_NUMBER_OF_XML_SHAPES ( 32 )
unsigned int g_XMLShapeUIDArray[ EMPIRE_NUMBER_OF_XML_SHAPES ];


//--------------------------------------------------------------------------------------
// UI control IDs
//--------------------------------------------------------------------------------------
#define IDC_TOGGLEFULLSCREEN    1
#define IDC_TOGGLEREF           2
#define IDC_CHANGEDEVICE        3

//--------------------------------------------------------------------------------------
// Forward declarations 
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
                          void* pUserContext );
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );

bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
                                      bool bWindowed, void* pUserContext );
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext );
HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                    void* pUserContext );
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
void CALLBACK OnD3D9LostDevice( void* pUserContext );
void CALLBACK OnD3D9DestroyDevice( void* pUserContext );

void InitApp();
void RenderText( D3DXMATRIX mWorld, D3DXMATRIX mView, D3DXMATRIX mProj );

//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing 
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // DXUT will create and use the best device (either D3D9 or D3D10) 
    // that is available on the system depending on which D3D callbacks are set below

    // Set DXUT callbacks
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackKeyboard( OnKeyboard );
	DXUTSetConstantFrameTime( true, SECONDS_PER_FRAME );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );

    DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
    DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
    DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
    DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
    DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
    DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );

    InitApp();
    DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
    DXUTSetCursorSettings( true, true );
    DXUTCreateWindow( L"Empire" );
    DXUTCreateDevice( true, 640, 480 );
    DXUTMainLoop(); // Enter into the DXUT render loop

    return DXUTGetExitCode();
}

//--------------------------------------------------------------------------------------
// Initialize the app 
//--------------------------------------------------------------------------------------
void InitApp()
{
    g_SettingsDlg.Init( &g_DialogResourceManager );
    g_HUD.Init( &g_DialogResourceManager );
    g_SampleUI.Init( &g_DialogResourceManager );

    g_HUD.SetCallback( OnGUIEvent ); int iY = 10;
    g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
    g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22, VK_F3 );
    g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22, VK_F2 );

    g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;

	Empire::initialise();	
}


//--------------------------------------------------------------------------------------
// Render the help and statistics text. This function uses the ID3DXFont interface for 
// efficient text rendering.
//--------------------------------------------------------------------------------------
void RenderMatrixText( WCHAR const * const name, D3DXMATRIX matrix )
{
	const int strBufferLength = 512;
	static WCHAR strBuffer[ strBufferLength ];
	int strLength = 0;
	int strBufferOffset = 0;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset, 
		L"%s[ 0 ] [ \t%.2f, \t%.2f, \t%.2f, \t%.2f ]", name,
		matrix.m[ 0 ][ 0 ], matrix.m[ 0 ][ 1 ], matrix.m[ 0 ][ 2 ], matrix.m[ 0 ][ 3 ] );
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset,
		L"%s[ 1 ] [ \t%.2f, \t%.2f, \t%.2f, \t%.2f ]", name,
		matrix.m[ 1 ][ 0 ], matrix.m[ 1 ][ 1 ], matrix.m[ 1 ][ 2 ], matrix.m[ 1 ][ 3 ] );	
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset,
		L"%s[ 2 ] [ \t%.2f, \t%.2f, \t%.2f, \t%.2f ]", name,
		matrix.m[ 2 ][ 0 ], matrix.m[ 2 ][ 1 ], matrix.m[ 2 ][ 2 ], matrix.m[ 2 ][ 3 ] );	
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset,
		L"%s[ 3 ] [ \t%.2f, \t%.2f, \t%.2f, \t%.2f ]", name,
		matrix.m[ 3 ][ 0 ], matrix.m[ 3 ][ 1 ], matrix.m[ 3 ][ 2 ], matrix.m[ 3 ][ 3 ] );	
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;
}

void RenderShapeText( 
	Physics::ShapeClass const & shape,
	WCHAR const * const name )
{
	const int strBufferLength = 512;
	static WCHAR strBuffer[ strBufferLength ];
	int strLength = 0;
	int strBufferOffset = 0;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset, 
		L"Shape %s", name );
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;	

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset, 
		L"area %.2f", shape.area() );
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset, 
		L"mass %.2f", shape.mass() );
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset, 
		L"center of mass [ \t%.2f, \t%.2f ]", shape.centerOfMassLocalPosition().x, shape.centerOfMassLocalPosition().y );
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;

	strLength = swprintf_s( 
		strBuffer + strBufferOffset, 
		strBufferLength - strBufferOffset, 
		L"moment of inertia %.2f", shape.momentOfInertia() );
	g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
	strBufferOffset += strLength;
}

void RenderText( D3DXMATRIX mWorld, D3DXMATRIX mView, D3DXMATRIX mProj )
{
    g_pTxtHelper->Begin();
    g_pTxtHelper->SetInsertionPos( 5, 5 );
    g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
    g_pTxtHelper->DrawTextLine( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
    g_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() );
	
	//RenderShapeText( g_shape, L"SHAPE" );
	//RenderShapeText( g_floorShape, L"FLOOR" );
	//RenderMatrixText( L"mWorld", mWorld );
	//RenderMatrixText( L"mView", mView );
	//RenderMatrixText( L"mProj", mProj ); 
	
	{
		const int strBufferLength = 512;
		static WCHAR strBuffer[ strBufferLength ];
		int strLength = 0;
		int strBufferOffset = 0;

		strLength = swprintf_s( 
			strBuffer + strBufferOffset, 
			strBufferLength - strBufferOffset, 
			L"Last Mouse Position [ %d, %d ]", g_ptLastMousePosition.x, g_ptLastMousePosition.y );
		g_pTxtHelper->DrawTextLine( strBuffer + strBufferOffset );
		strBufferOffset += strLength;
	}

    g_pTxtHelper->End();
}


//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat,
                                      D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
    // Skip backbuffer formats that don't support alpha blending
    IDirect3D9* pD3D = DXUTGetD3D9Object();
    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
                                         AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
                                         D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    // No fallback defined by this app, so reject any device that 
    // doesn't support at least ps2.0
    if( pCaps->PixelShaderVersion < D3DPS_VERSION( 2, 0 ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Called right before creating a D3D9 or D3D10 device, allowing the app to modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
    if( pDeviceSettings->ver == DXUT_D3D9_DEVICE )
    {
        IDirect3D9* pD3D = DXUTGetD3D9Object();
        D3DCAPS9 Caps;
        pD3D->GetDeviceCaps( pDeviceSettings->d3d9.AdapterOrdinal, pDeviceSettings->d3d9.DeviceType, &Caps );

        // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
        // then switch to SWVP.
        if( ( Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == 0 ||
            Caps.VertexShaderVersion < D3DVS_VERSION( 1, 1 ) )
        {
            pDeviceSettings->d3d9.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }

        // Debugging vertex shaders requires either REF or software vertex processing 
        // and debugging pixel shaders requires REF.  
#ifdef DEBUG_VS
        if( pDeviceSettings->d3d9.DeviceType != D3DDEVTYPE_REF )
        {
            pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
            pDeviceSettings->d3d9.BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
            pDeviceSettings->d3d9.BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
        }
#endif
#ifdef DEBUG_PS
        pDeviceSettings->d3d9.DeviceType = D3DDEVTYPE_REF;
#endif
    }

    // For the first device created if its a REF device, optionally display a warning dialog box
    static bool s_bFirstTime = true;
    if( s_bFirstTime )
    {
        s_bFirstTime = false;
        if( ( DXUT_D3D9_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF ) ||
            ( DXUT_D3D10_DEVICE == pDeviceSettings->ver &&
              pDeviceSettings->d3d10.DriverType == D3D10_DRIVER_TYPE_REFERENCE ) )
            DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
    }

    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext )
{
    HRESULT hr;

    V_RETURN( g_DialogResourceManager.OnD3D9CreateDevice( pd3dDevice ) );
    V_RETURN( g_SettingsDlg.OnD3D9CreateDevice( pd3dDevice ) );

    V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
                              OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
                              L"Arial", &g_pFont9 ) );

    // Read the D3DX effect file
    WCHAR str[MAX_PATH];
    DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;
#ifdef DEBUG_VS
        dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
    #endif
#ifdef DEBUG_PS
        dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
    #endif
    V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"empire.fx" ) );
    V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags,
                                        NULL, &g_pEffect9, NULL ) );

    // Setup the camera's view parameters
    D3DXVECTOR3 vecEye( 0.0f, 0.0f, -50.0f );
    D3DXVECTOR3 vecAt ( 0.0f, 0.0f, 0.0f );
    g_Camera.SetViewParams( &vecEye, &vecAt );

	#if 0
	{
		TiXmlDocument doc( "C://Resources//untitled.dav" );

		const bool fileLoaded = doc.LoadFile();
		assert( fileLoaded );

		const TiXmlElement* const davElPtr = doc.RootElement();
		assert( davElPtr != 0 );
		assert( davElPtr->ValueStr() == "dav" );
	
		const TiXmlElement* sceneElPtr = davElPtr->FirstChildElement( "scene" );
		if( sceneElPtr != 0 )
		{
			const std::string objectStr( "object" );	
			for(	const TiXmlElement* objectElPtr = sceneElPtr->FirstChildElement( objectStr ); 
					objectElPtr != 0;
					objectElPtr = objectElPtr->NextSiblingElement( objectStr ) )
			{				
				// Name
				std::string name;
				objectElPtr->QueryStringAttribute( "name", &name );
				//const std::string name = objectElPtr->GetText();	

				// infiniteMass
				bool infiniteMass = false;
				objectElPtr->QueryBoolAttribute( "infiniteMass", &infiniteMass );
								
				// Transformation
				D3DXMATRIX transformation;
				const std::string transformationStr( "transformation" );
				const TiXmlElement* const transformationElPtr = objectElPtr->FirstChildElement( transformationStr ); 
				assert( transformationElPtr != 0 );
				transformationElPtr->QueryFloatAttribute( "_00", &transformation._11 );
				transformationElPtr->QueryFloatAttribute( "_01", &transformation._12 );
				transformationElPtr->QueryFloatAttribute( "_02", &transformation._13 );
				transformationElPtr->QueryFloatAttribute( "_03", &transformation._14 );

				transformationElPtr->QueryFloatAttribute( "_10", &transformation._21 );
				transformationElPtr->QueryFloatAttribute( "_11", &transformation._22 );
				transformationElPtr->QueryFloatAttribute( "_12", &transformation._23 );
				transformationElPtr->QueryFloatAttribute( "_13", &transformation._24 );

				transformationElPtr->QueryFloatAttribute( "_20", &transformation._31 );
				transformationElPtr->QueryFloatAttribute( "_21", &transformation._32 );
				transformationElPtr->QueryFloatAttribute( "_22", &transformation._33 );
				transformationElPtr->QueryFloatAttribute( "_23", &transformation._34 );

				transformationElPtr->QueryFloatAttribute( "_30", &transformation._41 );
				transformationElPtr->QueryFloatAttribute( "_31", &transformation._42 );
				transformationElPtr->QueryFloatAttribute( "_32", &transformation._43 );
				transformationElPtr->QueryFloatAttribute( "_33", &transformation._44 );

				Dav::ObjectClass object( name, infiniteMass, transformation );

				// Verticies
				const std::string vertexStr( "vertex" );	
				for(	const TiXmlElement* vertexElPtr = objectElPtr->FirstChildElement( vertexStr ); 
						vertexElPtr != 0;
						vertexElPtr = vertexElPtr->NextSiblingElement( vertexStr ) )
				{	
					D3DXVECTOR4 vertexPosition( 0.0f, 0.0f, 0.0f, 1.0f );
					vertexElPtr->QueryFloatAttribute( "x", &vertexPosition.x );
					vertexElPtr->QueryFloatAttribute( "y", &vertexPosition.y );
					vertexElPtr->QueryFloatAttribute( "z", &vertexPosition.z );
					vertexElPtr->QueryFloatAttribute( "w", &vertexPosition.w );

					Dav::VertexClass vertex( vertexPosition );

					object.addVertex( vertex );
				}
				
				// Faces
				const std::string faceStr( "face" );	
				for(	const TiXmlElement* faceElPtr = objectElPtr->FirstChildElement( faceStr ); 
						faceElPtr != 0;
						faceElPtr = faceElPtr->NextSiblingElement( faceStr ) )
				{	
					Dav::FaceClass face;

					// Vertex
					const std::string vertexStr( "vertex" );	
					for(	const TiXmlElement* vertexElPtr = faceElPtr->FirstChildElement( vertexStr ); 
							vertexElPtr != 0;
							vertexElPtr = vertexElPtr->NextSiblingElement( vertexStr ) )
					{
						int vertexIdx = 0;
						vertexElPtr->QueryIntAttribute( "idx", &vertexIdx );

						face.addVertexIdx( vertexIdx );
					}

					object.addFace( face );
				}

				Empire::g_davScene.addObject( object );
			}
		}
	}
	#endif

	#if 1
	{
		int XMLShapeIdx = 0;
		for( XMLShapeIdx = 0; XMLShapeIdx != EMPIRE_NUMBER_OF_XML_SHAPES; ++XMLShapeIdx )
		{
			g_XMLShapeUIDArray[ XMLShapeIdx ] = PHYSICS_SHAPE_NULL_UID;
		}
		XMLShapeIdx = 0;

		for(	Dav::ObjectVectorType::const_iterator objectItr = Empire::g_davScene.objectVector().begin();
				objectItr != Empire::g_davScene.objectVector().end();
				++objectItr )
		{		
			for(	Dav::FaceVectorType::const_iterator faceItr = objectItr->faceVector().begin();
					faceItr != objectItr->faceVector().end();
					++faceItr )
			{
				Physics::D3DXVECTOR4VectorType shapeVertexVector;

				for(	Dav::VertexIdxVectorType::const_iterator vertexIdxItr = faceItr->vertexIdxVector().begin();
						vertexIdxItr != faceItr->vertexIdxVector().end();
						++vertexIdxItr )
				{
					assert( *vertexIdxItr < ( int )objectItr->vertexVector().size() );
					shapeVertexVector.push_back( objectItr->vertexVector()[ *vertexIdxItr ].position() );
				}

				const D3DXVECTOR4 xAxis = objectItr->transformation().m[ 0 ];
				const float orientation = atan2f( xAxis.y, xAxis.x );				

				assert( XMLShapeIdx != EMPIRE_NUMBER_OF_XML_SHAPES );
				g_XMLShapeUIDArray[ XMLShapeIdx ] = Empire::g_physicsEngine.createShape(
					shapeVertexVector, // D3DXVECTOR4VectorType const & vertexVector,
					objectItr->transformation().m[ 3 ], // objectItr->position(), // D3DXVECTOR4( -12.193243f, 7.0f, 0.000000f, 1.000000f ), // shapePositions[ shapeIndex ],
					orientation, // shapeOrientations[ shapeIndex ],
					D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & velocity,
					0.0f, // float angularVelocity );
					D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & force,
					0.0f, // float torque );
					objectItr->infiniteMass() );
				++XMLShapeIdx;
			}
		}
	}
	#endif
	
	#if 0
	{
		int XMLShapeIdx = 0;
		for( XMLShapeIdx = 0; XMLShapeIdx != EMPIRE_NUMBER_OF_XML_SHAPES; ++XMLShapeIdx )
		{
			g_XMLShapeUIDArray[ XMLShapeIdx ] = PHYSICS_SHAPE_NULL_UID;
		}
		XMLShapeIdx = 0;

		TiXmlDocument doc( "C://Resources//untitled.dav" );
		//TiXmlDocument doc( "C://temp//test.dav" );

		const bool fileLoaded = doc.LoadFile();
		assert( fileLoaded );

		const TiXmlElement* const davElPtr = doc.RootElement();
		assert( davElPtr != 0 );
		assert( davElPtr->ValueStr() == "dav" );
	
		const TiXmlElement* sceneElPtr = davElPtr->FirstChildElement( "scene" );
		if( sceneElPtr != 0 )
		{
			const std::string objStr( "obj" );	
			for(	const TiXmlElement* objElPtr = sceneElPtr->FirstChildElement( objStr ); 
					( objElPtr != 0 ) && ( XMLShapeIdx != EMPIRE_NUMBER_OF_XML_SHAPES ); 
					objElPtr = objElPtr->NextSiblingElement( objStr ) )
			{
				Physics::D3DXVECTOR4VectorType shapeVertexVector;

				const std::string vertStr( "vert" );	
				for(	const TiXmlElement* vertElPtr = objElPtr->FirstChildElement( vertStr ); 
						( vertElPtr != 0 ) && ( shapeVertexVector.full() == false ); 
						vertElPtr = vertElPtr->NextSiblingElement( vertStr ) )
				{	
					float x, y, z, w;
					vertElPtr->QueryFloatAttribute("x", &x);
					vertElPtr->QueryFloatAttribute("y", &y);
					vertElPtr->QueryFloatAttribute("z", &z);
					vertElPtr->QueryFloatAttribute("w", &w);

					if( shapeVertexVector.size() != 3 )
						shapeVertexVector.push_back( D3DXVECTOR4( x, y, z, w ) );
				}

				// Position
				const std::string posStr( "pos" );
				const TiXmlElement* const posElPtr = objElPtr->FirstChildElement( posStr ); 
				assert( posElPtr != 0 );
				D3DXVECTOR4 pos;
				{	
					//float x, y, z, w;
					posElPtr->QueryFloatAttribute("x", &pos.x);
					posElPtr->QueryFloatAttribute("y", &pos.y);
					posElPtr->QueryFloatAttribute("z", &pos.z);
					posElPtr->QueryFloatAttribute("w", &pos.w);

					//shapeVertexVector.push_back( D3DXVECTOR4( x, y, z, w ) );
				}

				assert( XMLShapeIdx != EMPIRE_NUMBER_OF_XML_SHAPES );
				g_XMLShapeUIDArray[ XMLShapeIdx ] = Empire::g_physicsEngine.createShape(
					shapeVertexVector, // D3DXVECTOR4VectorType const & vertexVector,
					pos, // D3DXVECTOR4( -12.193243f, 7.0f, 0.000000f, 1.000000f ), // shapePositions[ shapeIndex ],
					0.0f, // shapeOrientations[ shapeIndex ],
					D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & velocity,
					0.0f, // float angularVelocity );
					D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & force,
					0.0f, // float torque );
					false ); // infinite mass
				++XMLShapeIdx;
			}
		}
	}
	#endif


	#if 0
	{	
		DWORD numMaterials = 0;
		LPD3DXMESH pMesh = 0;

		const HRESULT loadMeshResult = D3DXLoadMeshFromX(
			L"C:/Resources/helloWorld.x", // LPCWSTR pFilename, 
			//D3DXMESH_32BIT                   |
			//D3DXMESH_DONOTCLIP               |
			//D3DXMESH_POINTS                  |
			//D3DXMESH_RTPATCHES               |
			//D3DXMESH_NPATCHES                |
			//D3DXMESH_VB_SYSTEMMEM            |
			//D3DXMESH_VB_MANAGED              |
			//D3DXMESH_VB_WRITEONLY            |
			//D3DXMESH_VB_DYNAMIC              |
			//D3DXMESH_VB_SOFTWAREPROCESSING   |
			//D3DXMESH_IB_SYSTEMMEM            |
			//D3DXMESH_IB_MANAGED              |
			//D3DXMESH_IB_WRITEONLY            |
			//D3DXMESH_IB_DYNAMIC              |
			//D3DXMESH_IB_SOFTWAREPROCESSING   |
			//D3DXMESH_VB_SHARE                |
			//D3DXMESH_USEHWONLY               |
			//D3DXMESH_SYSTEMMEM               |
			//D3DXMESH_MANAGED                 |
			//D3DXMESH_WRITEONLY               |
			//D3DXMESH_DYNAMIC                 |
			//D3DXMESH_SOFTWAREPROCESSING      |
			0, // DWORD Options, 
			pd3dDevice, // LPDIRECT3DDEVICE9 pD3DDevice, 
			0, // LPD3DXBUFFER *ppAdjacency,
			0, // LPD3DXBUFFER *ppMaterials, 
			0, // LPD3DXBUFFER *ppEffectInstances, 
			&numMaterials, //DWORD *pNumMaterials,
			&pMesh );

		if( loadMeshResult == D3D_OK )
		{
			printf( "poo\n" );
		}
	}
	#endif

	#if HARDCODED_SHAPES_ON
	{				
		static D3DXVECTOR4 const shapePositions[] =
		{
			D3DXVECTOR4( 0.000000f, -12.000000f, 0.000000f, 1.000000f ),			
			D3DXVECTOR4( -12.193243f, 7.0f, 0.000000f, 1.000000f ), // 
			//D3DXVECTOR4( -12.0f, 5.3f, 0.000000f, 1.000000f ),
			//D3DXVECTOR4( -12.193243f, -6.498757f, 0.000000f, 1.000000f ), //D3DXVECTOR4( -12.193243f, -4.5f, 0.000000f, 1.000000f ), // 
			D3DXVECTOR4( 10.926556f, 5.805245f, 0.000000f, 1.000000f ),
		};

		static float const shapeOrientations[] =
		{
			0.000000f,
			0.000000f,
			D3DX_PI / 4.0f,
			//0.000243f,
			//1.062378f,
		};


		//static D3DXVECTOR4 const shapePositions[] =
		//{
		//	D3DXVECTOR4( 0.000000f, -12.000000f, 0.000000f, 1.000000f ),			
		//	D3DXVECTOR4( -12.0f, -6.9f, 0.000000f, 1.000000f ), //D3DXVECTOR4( -12.193243f, -4.5f, 0.000000f, 1.000000f ), // 
		//	D3DXVECTOR4( -12.0f, 5.3f, 0.000000f, 1.000000f ),

		//	//5.0645285
		//	//-6.9999642
		//	//D3DXVECTOR4( -12.193243f, -6.498757f, 0.000000f, 1.000000f ), //D3DXVECTOR4( -12.193243f, -4.5f, 0.000000f, 1.000000f ), // 
		//	//D3DXVECTOR4( -10.926556f, 5.805245f, 0.000000f, 1.000000f ),
		//};

		//static float const shapeOrientations[] =
		//{
		//	0.000000f,
		//	0.000000f,
		//	D3DX_PI / 4.0f,


		//	//0.000243f,
		//	//1.062378f,
		//};

		//static D3DXVECTOR4 const shapePositions[ ] =
		//{			
		//	D3DXVECTOR4( 0.0f, -12.0f, 0.0f, 1.0f ), // floor
		//	D3DXVECTOR4( -0.42521f, 9.46261f, 0.0f, 1.0f ),
		//	D3DXVECTOR4( 0.25709f, 8.76950f, 0.0f, 1.0f ), 
		//	//D3DXVECTOR4( -10.0f, -4.9289303f, 0.0f, 1.0f ), // D3DXVECTOR4( -10.0f, -7.7f, 0.0f, 1.0f ),//D3DXVECTOR4( -0.42521f, 9.46261f, 0.0f, 1.0f ),
		//	//D3DXVECTOR4( 0.0f, 10.0f, 0.0f, 1.0f ),	//D3DXVECTOR4( 0.25709f, 8.76950f, 0.0f, 1.0f ), 
		//	D3DXVECTOR4( 10.0f, 10.0f, 0.0f, 1.0f ), 
		//	D3DXVECTOR4( 0.0f, 25.0f, 0.0f, 1.0f ), 
		//};

		//static float const shapeOrientations[ ] =
		//{
		//	0.0f,
		//	D3DXToRadian( 40.0f ),
		//	1.0f,
		//	2.0f,
		//	3.0f,
		//};

		


		for( unsigned int shapeIndex = 0; shapeIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
		{
			const float squareSize = 5.0f;

			Physics::D3DXVECTOR4VectorType shapeVertexVector;
			if( shapeIndex == 0 )
			{					
				shapeVertexVector.push_back( D3DXVECTOR4( 20.0f, 0.0f, 0.0f, 1.0f ) );
				shapeVertexVector.push_back( D3DXVECTOR4( -20.0f, 0.0f, 0.0f, 1.0f ) );
				shapeVertexVector.push_back( D3DXVECTOR4( -20.0f, -4.0f, 0.0f, 1.0f ) );
				shapeVertexVector.push_back( D3DXVECTOR4( 20.0f, -4.0f, 0.0f, 1.0f ) );
			}
			else
			{
				shapeVertexVector.push_back( D3DXVECTOR4( squareSize, squareSize, 0.0f, 1.0f ) );
				shapeVertexVector.push_back( D3DXVECTOR4( squareSize, -squareSize, 0.0f, 1.0f ) );
				shapeVertexVector.push_back( D3DXVECTOR4( -squareSize, -squareSize, 0.0f, 1.0f ) );
				shapeVertexVector.push_back( D3DXVECTOR4( -squareSize, squareSize, 0.0f, 1.0f ) );

				//shapeVertexVector.push_back( D3DXVECTOR4( 4.0f, 3.0f, 0.0f, 1.0f ) );
				//shapeVertexVector.push_back( D3DXVECTOR4( 6.0f, 0.0f, 0.0f, 1.0f ) );
				//shapeVertexVector.push_back( D3DXVECTOR4( 2.0f, -4.0f, 0.0f, 1.0f ) );
				//shapeVertexVector.push_back( D3DXVECTOR4( -7.0f, -1.0f, 0.0f, 1.0f ) );
				//shapeVertexVector.push_back( D3DXVECTOR4( -5.0f, 2.0f, 0.0f, 1.0f ) );
			}

			g_shapeUIDArray[ shapeIndex ] = Empire::g_physicsEngine.createShape(
				shapeVertexVector, // D3DXVECTOR4VectorType const & vertexVector,
				shapePositions[ shapeIndex ],
				shapeOrientations[ shapeIndex ],
				D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & velocity,
				0.0f, // float angularVelocity );
				D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & force,
				0.0f, // float torque );
				( shapeIndex == 0 ) ); // infinite mass

			//g_shapeArray[ shapeIndex ] = Physics::ShapeClass( 
			//	shapeVertexVector, // D3DXVECTOR4VectorType const & vertexVector,
			//	shapePositions[ shapeIndex ],
			//	shapeorientations[ shapeIndex ],
			//	D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & velocity,
			//	0.0f ); // float angularVelocity );

			//g_featureArray[ shapeIndex ] = Physics::FeatureClass( Physics::VertexFeature, 0 );
		}
	}
	#endif

	


	//{
	//	Physics::D3DXVECTOR4VectorType shapeVertexVector;
	//	shapeVertexVector.push_back( D3DXVECTOR4( 4.0f, 3.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( 6.0f, 0.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( 2.0f, -4.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( -7.0f, -1.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( -5.0f, 2.0f, 0.0f, 1.0f ) );
	//	g_shape = Physics::ShapeClass( 
	//		shapeVertexVector, // D3DXVECTOR4VectorType const & vertexVector,
	//		D3DXVECTOR4( 0.0f, 7.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & position,
	//		0.0f, // float orientation,
	//		D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & velocity,
	//		0.0f ); // float angularVelocity );
	//}

	//{
	//	Physics::D3DXVECTOR4VectorType shapeVertexVector;
	//	//shapeVertexVector.push_back( D3DXVECTOR4( 10.0f, 5.0f, 0.0f, 1.0f ) );
	//	//shapeVertexVector.push_back( D3DXVECTOR4( -10.0f, 5.0f, 0.0f, 1.0f ) );
	//	//shapeVertexVector.push_back( D3DXVECTOR4( -10.0f, -5.0f, 0.0f, 1.0f ) );
	//	//shapeVertexVector.push_back( D3DXVECTOR4( 10.0f, -5.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( 20.0f, 0.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( -20.0f, 0.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( -20.0f, -4.0f, 0.0f, 1.0f ) );
	//	shapeVertexVector.push_back( D3DXVECTOR4( 20.0f, -4.0f, 0.0f, 1.0f ) );
	//	g_floorShape = Physics::ShapeClass( 
	//		shapeVertexVector, // D3DXVECTOR4VectorType const & vertexVector,
	//		D3DXVECTOR4( 0.0f, -12.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & position,
	//		0.0f, // float orientation,
	//		D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // D3DXVECTOR4 const & velocity,
	//		0.0f ); // float angularVelocity );
	//}	

	//{
	//	g_shapePairVector.clear();
	//	//g_shapePairVector.reserve( EMPIRE_NUMBER_OF_SHAPE_PAIRS );

	//	for( unsigned int shapeAIndex = 0; shapeAIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeAIndex )
	//	{
	//		//g_shapePairVector.push_back( Physics::ShapePairClass(		
	//		//	g_shapeArray[ shapeAIndex ], // ShapeClass & shapeA,
	//		//	Physics::FeatureClass( Physics::VertexFeature, 0 ),
	//		//	g_floorShape, // ShapeClass & shapeB,
	//		//	Physics::FeatureClass( Physics::VertexFeature, 0 ) ) );

	//		for( unsigned int shapeBIndex = ( shapeAIndex + 1 ); shapeBIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeBIndex )
	//		{
	//			g_shapePairVector.push_back( Physics::ShapePairClass(		
	//				g_shapeArray[ shapeAIndex ], // ShapeClass & shapeA,
	//				Physics::FeatureClass( Physics::VertexFeature, 0 ),
	//				g_shapeArray[ shapeBIndex ], // ShapeClass & shapeB,
	//				Physics::FeatureClass( Physics::VertexFeature, 0 ) ) );
	//		}
	//	}
	//}

	#if 1
	{
		const float unitLen = 2.0f;
		const float xAxisLen = 40.0f;
		float const xAxisStart = 0.0f; // -xAxisLen/2.0f;
		float const xAxisEnd = xAxisLen/2.0f;
		const float yAxisLen = 40.0f;
		float const yAxisStart = 0.0f; // -yAxisLen/2.0f;
		float const yAxisEnd = yAxisLen/2.0f;

		DevGraphics::line(
			23, // int UID,
			D3DXVECTOR4( -xAxisLen/2.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromPosition,
			D3DXVECTOR4( xAxisLen/2.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & toPosition,
			D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromColour,
			D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & toColour,
			true, // bool infiniteLife,
			5.0f ); // float lifeTime );

		DevGraphics::line(
			2111, // int UID,
			D3DXVECTOR4( 0.0f, -yAxisLen/2.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromPosition,
			D3DXVECTOR4( 0.0f, yAxisLen/2.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & toPosition,
			D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 1.0f ), // D3DXVECTOR4 const & fromColour,
			D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 1.0f ), // D3DXVECTOR4 const & toColour,
			true, // bool infiniteLife,
			5.0f ); // float lifeTime );

		for( float xAxisUnitPos = xAxisStart; xAxisUnitPos < xAxisEnd; xAxisUnitPos += unitLen )
		{
			DevGraphics::point( 
				965 + ( int )xAxisUnitPos, // int UID,
				D3DXVECTOR4( xAxisUnitPos, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromPosition,
				3.0f, // size
				D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & colour,
				true, // bool infiniteLife,
				0.1f ); // float lifeTime );
		}

		for( float yAxisUnitPos = yAxisStart; yAxisUnitPos < yAxisEnd; yAxisUnitPos += unitLen )
		{
			DevGraphics::point( 
				95 + ( int )yAxisUnitPos, // int UID,
				D3DXVECTOR4( 0.0f, yAxisUnitPos, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromPosition,
				3.0f, // size
				D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 1.0f ), // D3DXVECTOR4 const & colour,
				true, // bool infiniteLife,
				0.1f ); // float lifeTime );
		}


	}
	#endif


    return S_OK;
}


//--------------------------------------------------------------------------------------
// Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT) 
// or that are tied to the back buffer size 
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice,
                                    const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
    HRESULT hr;

    V_RETURN( g_DialogResourceManager.OnD3D9ResetDevice() );
    V_RETURN( g_SettingsDlg.OnD3D9ResetDevice() );

    if( g_pFont9 ) V_RETURN( g_pFont9->OnResetDevice() );
    if( g_pEffect9 ) V_RETURN( g_pEffect9->OnResetDevice() );

    V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pSprite9 ) );
    g_pTxtHelper = new CDXUTTextHelper( g_pFont9, g_pSprite9, NULL, NULL, 15 );

    // Setup the camera's projection parameters
    //float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
	Empire::g_aspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
    g_Camera.SetProjParams( EMPIRE_FOV, Empire::g_aspectRatio, EMPIRE_NEAR_CLIP_PLANE, EMPIRE_FAR_CLIP_PLANE );
    //g_Camera.SetProjParams( D3DX_PI / 4, fAspectRatio, 0.1f, 1000.0f );
	#if !defined( FIRST_PERSON_CAMERA )
    g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
	#endif

    g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 );
    g_HUD.SetSize( 170, 170 );
    g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 350 );
    g_SampleUI.SetSize( 170, 300 );

    return S_OK;
}

D3DXVECTOR4 rayPlaneIntersectionPosition(
	D3DXVECTOR4 const & planePosition,
	D3DXVECTOR4 const & planeNormalUnitDirection,
	D3DXVECTOR4 const & rayPosition,
	D3DXVECTOR4 const & rayDirection )
{
	float const rayDirectionDotPlaneNormalUnitDirection = D3DXVec4Dot( &rayDirection, &planeNormalUnitDirection );
	float rayPlaneIntersectionDistance = 0.0f;
	if( fabsf( rayDirectionDotPlaneNormalUnitDirection ) > 0.0f )
	{
		rayPlaneIntersectionDistance = 
			( D3DXVec4Dot( &planePosition, &planeNormalUnitDirection ) - D3DXVec4Dot( &rayPosition, &planeNormalUnitDirection ) ) / rayDirectionDotPlaneNormalUnitDirection;
	}
	return rayPosition + ( rayPlaneIntersectionDistance * rayDirection );
}

class PlaneClass
{
private:
	D3DXVECTOR4 m_pos;
	D3DXVECTOR4 m_unitNorm;

public:
	PlaneClass( const D3DXVECTOR4& pos, const D3DXVECTOR4& unitNorm )
		: m_pos( pos )
		, m_unitNorm( unitNorm )
	{
	}
	
	const D3DXVECTOR4& pos() const
	{
		return m_pos;
	}

	const D3DXVECTOR4& unitNorm() const
	{
		return m_unitNorm;
	}
};

typedef std::vector< PlaneClass > PlaneVectorType;

class RegionClass
{
private:
	PlaneVectorType m_planeVector;

public:
	RegionClass( const PlaneVectorType& planeVector )
		: m_planeVector( planeVector )
	{
	}
	
	const PlaneVectorType& planeVector() const
	{
		return m_planeVector;
	}
};

typedef std::vector< RegionClass > RegionVectorType;


//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{


	
	#if 0
	// GET CLOSEST
	{	
		const D3DXVECTOR4 points[] =
		{
			D3DXVECTOR4( 0.000000f, -12.000000f, 0.000000f, 1.000000f ),
			D3DXVECTOR4( -12.193243f, 7.0f, 0.000000f, 1.000000f ),
			D3DXVECTOR4( -12.0f, 5.3f, 0.000000f, 1.000000f ),
			D3DXVECTOR4( -12.193243f, -6.498757f, 0.000000f, 1.000000f ),
			D3DXVECTOR4( -12.193243f, -4.5f, 0.000000f, 1.000000f ),
			D3DXVECTOR4( 10.926556f, 5.805245f, 0.000000f, 1.000000f ),
		};
		const int numPoints = sizeof( points ) / sizeof( D3DXVECTOR4 );

		// Visualise points
		for( int pointIdx = 0; pointIdx != numPoints; ++pointIdx )
		{
			DevGraphics::point( 
				9675 + pointIdx, // int UID,
				points[ pointIdx ], // D3DXVECTOR4 const & position,
				12.0f, // size
				D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ), // D3DXVECTOR4 const & colour,
				false, // bool infiniteLife,
				0.1f ); // float lifeTime );
		}

		// Initialise region planes
		RegionVectorType regionVector;
		regionVector.reserve( numPoints );
		for( int dstPointIdx = 0; dstPointIdx != numPoints; ++dstPointIdx )
		{
			for( int scrPointIdx = 0; scrPointIdx != numPoints; ++scrPointIdx )
			{
				if( scrPointIdx != dstPointIdx )
				{
					const D3DXVECTOR4 dir = points[ dstPointIdx ] - points[ scrPointIdx ];
					const float dist = D3DXVec4Length( dir );

				}
			}
		}
	}
	#endif

	if( GetCapture() )
	{	
		if( g_bMouseLButtonDown || g_bMouseRButtonDown )
		{
			POINT ptCursor;
			GetCursorPos( &ptCursor );
			ScreenToClient( DXUTGetHWND(), &ptCursor );

			const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetD3D9BackBufferSurfaceDesc();
			float const temp = EMPIRE_NEAR_CLIP_PLANE * tanf( EMPIRE_FOV * 0.5f );
			D3DXVECTOR4 clipPlanePosition;
			clipPlanePosition.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) * temp;
			clipPlanePosition.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) * temp;
			clipPlanePosition.z = EMPIRE_NEAR_CLIP_PLANE;
			clipPlanePosition.w = 1.0f;
			
			const D3DXMATRIX cameraMatrix = *( g_Camera.GetWorldMatrix() );
			D3DXVECTOR4 const dragRayPosition = cameraMatrix.m[ 3 ];		
			D3DXVECTOR4 const dragRayDirection =
				( *( ( D3DXVECTOR4 const * )&cameraMatrix.m[ 0 ] ) * clipPlanePosition.x ) +
				( *( ( D3DXVECTOR4 const * )&cameraMatrix.m[ 1 ] ) * clipPlanePosition.y ) +
				( *( ( D3DXVECTOR4 const * )&cameraMatrix.m[ 2 ] ) * clipPlanePosition.z );
			
			// loop over all the shapes to see which are intersected

			//unsigned int intersectedShapeIndex = EMPIRE_NUMBER_OF_SHAPES;
			//bool shapeIntersected = true;
			if( !g_bTranslationDrag && !g_bRotationDrag )
			//if( ( g_TranslationDragShapeIndex == EMPIRE_NUMBER_OF_SHAPES ) && 
				//( g_RotationDragShapeIndex == EMPIRE_NUMBER_OF_SHAPES ) )
			{
				g_oPreviousDragRayPosition = dragRayPosition;
				g_oPreviousDragRayDirection = dragRayDirection;

				const Physics::EngineShapeListType& shapeList = Empire::g_physicsEngine.shapeList();
				for( Physics::EngineShapeListType::const_iterator shapeItr = shapeList.begin(); shapeItr != shapeList.end(); ++shapeItr )
				{
					float t, u, v;
					if( shapeIntersect( *shapeItr, dragRayPosition, dragRayDirection, t, u, v ) )
					{
						g_IntersectedShapeIndex = shapeItr->UID();
					}
				}

				#if HARDCODED_SHAPES_ON
				for( unsigned int shapeIndex = 0; shapeIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
				{
					Physics::ShapeClass const * const shapePtr = Empire::g_physicsEngine.shape( g_shapeUIDArray[ shapeIndex ] );
					assert( shapePtr != 0 );
					float t, u, v;
					if( shapeIntersect( *shapePtr, dragRayPosition, dragRayDirection, t, u, v ) )
					{
						g_IntersectedShapeIndex = shapeIndex;
					}
				}
				#endif
	
				//shapeIntersected = shapeIntersect( g_shape, dragRayPosition, dragRayDirection, t, u, v );	
			}	

			//if( shapeIntersected )
			//if( g_IntersectedShapeIndex != EMPIRE_NUMBER_OF_SHAPES )
			if( g_IntersectedShapeIndex != PHYSICS_SHAPE_NULL_UID )
			{	
				Physics::ShapeClass* const shapePtr = Empire::g_physicsEngine.shape( g_IntersectedShapeIndex );
				//Physics::ShapeClass * const shapePtr = Empire::g_physicsEngine.shape( g_shapeUIDArray[ g_IntersectedShapeIndex ] );
				assert( shapePtr != 0 );			

				D3DXVECTOR4 const shapePosition = shapePtr->dynamics().position();
				//D3DXVECTOR4 const shapePosition = g_shape.position();
				D3DXVECTOR4 const shapeUnitDirection( 0.0f, 0.0f, -1.0f, 0.0f );

				D3DXVECTOR4 const previousDragRayPlanePosition = rayPlaneIntersectionPosition(
					shapePosition, // D3DXVECTOR4 const & planePosition,
					shapeUnitDirection, // D3DXVECTOR4 const & planeNormalUnitDirection,
					g_oPreviousDragRayPosition, // D3DXVECTOR4 const & rayPosition,
					g_oPreviousDragRayDirection ); // D3DXVECTOR4 const & rayDirection )

				D3DXVECTOR4 const dragRayPlanePosition = rayPlaneIntersectionPosition(
					shapePosition, // D3DXVECTOR4 const & planePosition,
					shapeUnitDirection, // D3DXVECTOR4 const & planeNormalUnitDirection,
					dragRayPosition, // D3DXVECTOR4 const & rayPosition,
					dragRayDirection ); // D3DXVECTOR4 const & rayDirection )
						
				D3DXVECTOR4 translation( 0.0f, 0.0f, 0.0f, 0.0f );
				if( g_bMouseLButtonDown )
				{
					translation = dragRayPlanePosition - previousDragRayPlanePosition;
					
					//g_TranslationDragShapeIndex = g_IntersectedShapeIndex;
					g_bTranslationDrag = true;
				}

				float rotation = 0.0f;
				if( g_bMouseRButtonDown )
				{
					D3DXVECTOR4 shapeToPreviousDragRayUnitDirection = previousDragRayPlanePosition - shapePosition;		
					D3DXVec4Normalize( &shapeToPreviousDragRayUnitDirection, &shapeToPreviousDragRayUnitDirection );
					
					D3DXVECTOR4 shapeToDragRayUnitDirection = dragRayPlanePosition - shapePosition;		
					D3DXVec4Normalize( &shapeToDragRayUnitDirection, &shapeToDragRayUnitDirection );

					float rotationDot = D3DXVec4Dot( &shapeToPreviousDragRayUnitDirection, &shapeToDragRayUnitDirection );
					if( rotationDot > 1.0f ) rotationDot = 1.0f;
					if( rotationDot < -1.0f ) rotationDot = -1.0f;
					rotation = ( float )acosf( rotationDot );

					D3DXVECTOR4 rotationDirectionVec;
					D3DXVec4Cross( &rotationDirectionVec, &shapeToDragRayUnitDirection, &shapeToPreviousDragRayUnitDirection, &Misc::origin() );
					float const rotationDirection = D3DXVec4Dot( &rotationDirectionVec, &shapeUnitDirection );

					if( rotationDirection < 0.0f )
					{
						rotation *= -1.0f;
					}
	
					g_bRotationDrag = true;
				}			

				shapePtr->setDynamics(
					shapePtr->dynamics().position() + translation, // D3DXVECTOR4 const & position,
					shapePtr->dynamics().orientation() + rotation, // float const orientation,
					D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), // shapePtr->dynamics().velocity(), // D3DXVECTOR4 const & velocity,
					0.0f ); // shapePtr->dynamics().angularVelocity() );

				g_oPreviousDragRayPosition = dragRayPosition;
				g_oPreviousDragRayDirection = dragRayDirection;
			}
			else
			{	
				g_IntersectedShapeIndex = PHYSICS_SHAPE_NULL_UID; // EMPIRE_NUMBER_OF_SHAPES;
				g_bTranslationDrag = false;
				g_bRotationDrag = false;
			}
		}
		else
		{
			g_IntersectedShapeIndex = PHYSICS_SHAPE_NULL_UID; // EMPIRE_NUMBER_OF_SHAPES;
			g_bTranslationDrag = false;
			g_bRotationDrag = false;
		}		
	}
	else
	{
		g_IntersectedShapeIndex = PHYSICS_SHAPE_NULL_UID; // EMPIRE_NUMBER_OF_SHAPES;
		g_bTranslationDrag = false;
		g_bRotationDrag = false;
	}

	if( !Empire::g_inputActionArray[ Empire::gravityInputAction ] &&
		Empire::g_previousInputActionArray[ Empire::gravityInputAction ] )
	{
		Empire::g_applyGravity = !Empire::g_applyGravity;
	}
	
	if( Empire::g_inputActionArray[ Empire::outputStateInputAction ] )
	{
		const int strBufferLength = 256;
		static WCHAR strBuffer[ strBufferLength ];		
		
		swprintf_s( strBuffer, strBufferLength,	L"\n\n\nSHAPE STATE ======================== step [ %d ]\n", Empire::g_physicsEngine.stepCount() );
		DXUTOutputDebugString( strBuffer );

		swprintf_s( strBuffer, strBufferLength,	L"static D3DXVECTOR4 const shapePositions[] =\n{\n" );
		DXUTOutputDebugString( strBuffer );

		int shapeIdx = 0;
		for(	Physics::EngineShapeListType::const_iterator shapeItr = Empire::g_physicsEngine.shapeList().begin();
				shapeItr != Empire::g_physicsEngine.shapeList().end(); ++shapeItr, ++shapeIdx )
		{	
			const D3DXVECTOR4 position = shapeItr->dynamics().position();
			swprintf_s( strBuffer, strBufferLength,	
				L"\tD3DXVECTOR4( %ff, %ff, %ff, %ff ),\n",
				position.x, position.y, position.z, position.w );
			DXUTOutputDebugString( strBuffer );
		}

		swprintf_s( strBuffer, strBufferLength,	L"};\n\n" );
		DXUTOutputDebugString( strBuffer );		

		swprintf_s( strBuffer, strBufferLength,	L"static float const shapeOrientations[] =\n{\n" );
		DXUTOutputDebugString( strBuffer );

		shapeIdx = 0;
		for(	Physics::EngineShapeListType::const_iterator shapeItr = Empire::g_physicsEngine.shapeList().begin();
				shapeItr != Empire::g_physicsEngine.shapeList().end(); ++shapeItr, ++shapeIdx )
		{				
			swprintf_s( strBuffer, strBufferLength,	L"\t%ff,\n", shapeItr->dynamics().orientation() );
			DXUTOutputDebugString( strBuffer );
		}

		swprintf_s( strBuffer, strBufferLength,	L"};\n\n" );
		DXUTOutputDebugString( strBuffer );


		
		
		//static D3DXVECTOR4 const shapePositions[ ] =
		//{			
		//	D3DXVECTOR4( 0.0f, -12.0f, 0.0f, 1.0f ), // floor
		//	D3DXVECTOR4( -10.0f, -4.9289303f, 0.0f, 1.0f ), // D3DXVECTOR4( -10.0f, -7.7f, 0.0f, 1.0f ),//D3DXVECTOR4( -0.42521f, 9.46261f, 0.0f, 1.0f ),
		//	D3DXVECTOR4( 0.0f, 10.0f, 0.0f, 1.0f ),	//D3DXVECTOR4( 0.25709f, 8.76950f, 0.0f, 1.0f ), 
		//	D3DXVECTOR4( 10.0f, 10.0f, 0.0f, 1.0f ), 
		//	D3DXVECTOR4( 0.0f, 25.0f, 0.0f, 1.0f ), 
		//};

		//static float const shapeOrientations[ ] =
		//{
		//	0.0f,
		//	D3DXToRadian( 40.0f ),
		//	1.0f,
		//	2.0f,
		//	3.0f,
		//};

			
		
		//swprintf_s( strBuffer, strBufferLength,	L"\n\n\nSHAPE STATE ======================== step [ %d ]\n", Empire::g_physicsEngine.stepCount() );
		//DXUTOutputDebugString( strBuffer );

		//int shapeIdx = 0;
		//for(	Physics::EngineShapeListType::const_iterator shapeItr = Empire::g_physicsEngine.shapeList().begin();
		//		shapeItr != Empire::g_physicsEngine.shapeList().end(); ++shapeItr, ++shapeIdx )
		//{			
		//	swprintf_s( strBuffer, strBufferLength,	L"\nshape %d -\n", shapeIdx );			
		//	DXUTOutputDebugString( strBuffer );

		//	const D3DXVECTOR4 position = shapeItr->dynamics().position();
		//	swprintf_s( strBuffer, strBufferLength,	
		//		L"D3DXVECTOR4( %ff, %ff, %ff, %ff ), // POSITION\n",
		//		position.x, position.y, position.z, position.w );
		//	DXUTOutputDebugString( strBuffer );

		//	swprintf_s( strBuffer, strBufferLength,	L"%ff, // ORIENTATION\n", shapeItr->dynamics().orientation() );
		//	DXUTOutputDebugString( strBuffer );
		//}
	}





			
	//if( Empire::g_inputActionArray[ Empire::vClipIterationInputAction ] )
	//{
	//	g_VClipState = Physics::shapeSingleVClipIteration(			
	//		g_shapeArray[ 0 ], g_featureArray[ 0 ],			
	//		g_shapeArray[ 1 ], g_featureArray[ 1 ] );
	//}	
	

	for( unsigned int XMLShapeIndex = 0; XMLShapeIndex != EMPIRE_NUMBER_OF_XML_SHAPES; ++XMLShapeIndex )
	{
		if( g_XMLShapeUIDArray[ XMLShapeIndex ] != PHYSICS_SHAPE_NULL_UID )
		{
			Physics::ShapeClass * const shapePtr = Empire::g_physicsEngine.shape( g_XMLShapeUIDArray[ XMLShapeIndex ] );
			assert( shapePtr != 0 );

			D3DXVECTOR4 totalForce( 0.0f, 0.0f, 0.0f, 0.0f );
			float totalTorque = 0.0f;
		
			if( Empire::g_applyGravity )
			{	
				D3DXVECTOR4 const forceDueToGravity = Empire::g_accelerationDueToGravity * shapePtr->mass();

				totalForce += forceDueToGravity;
			}
			
			shapePtr->setForce( totalForce );
			shapePtr->setTorque( totalTorque );

			//{				
			//	//const D3DXVECTOR3 positionVec3( 0.0f, 0.0f, 0.0f );
			//	//const D3DXVECTOR3 rotationCenter( 0.0f, 0.0f, 0.0f );
			//	//D3DXMATRIX mat;
			//	//D3DXMatrixAffineTransformation( 
			//	//	&mat, // D3DXMATRIX *pOut, 
			//	//	1.0f, // FLOAT Scaling, 
			//	//	&rotationCenter,
			//	//	&quat, // CONST D3DXQUATERNION *pRotation, 
			//	//	&positionVec3 ); // CONST D3DXVECTOR3 *pTranslation);

			//	//D3DXVECTOR4 pos = shapePtr->position();
			//	//D3DXVECTOR4 dir( mat._11, mat._12, mat._13, mat._14 );

			//	const D3DXMATRIX mat = Empire::g_davScene.objectVector()[ 0 ].transformation();
			//	const D3DXVECTOR4 pos = mat.m[ 3 ];
			//	const D3DXVECTOR4 dir = mat.m[ 0 ];

			//	DevGraphics::line(
			//		62239, // int UID,
			//		pos, // D3DXVECTOR4 const & fromPosition,
			//		pos + ( dir * 10.0f ), // D3DXVECTOR4 const & toPosition,
			//		D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & fromColour,
			//		D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ), // D3DXVECTOR4 const & toColour,
			//		false, // bool infiniteLife,
			//		0.1f ); // float lifeTime );
			//}

		}
	}
	
	#if HARDCODED_SHAPES_ON
	for( unsigned int shapeIndex = 0; shapeIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
	{
		Physics::ShapeClass * const shapePtr = Empire::g_physicsEngine.shape( g_shapeUIDArray[ shapeIndex ] );
		assert( shapePtr != 0 );

		//g_shapeGravityApplied = false;
		//g_shapeForce0Applied = false;
		//g_shapeForce1Applied = false;

		D3DXVECTOR4 totalForce( 0.0f, 0.0f, 0.0f, 0.0f );
		float totalTorque = 0.0f;
		
		//if( ( Empire::g_inputActionArray[ Empire::gravityInputAction ] ) && ( shapeIndex != 0 ) )
		//{	
		//	g_shapeGravityApplied = true;

		//	D3DXVECTOR4 const forceDueToGravity = Empire::g_accelerationDueToGravity * shapePtr->mass();

		//	totalForce += forceDueToGravity;
		//}
		
		if( Empire::g_applyGravity ) // && ( shapeIndex != 0 ) )
		{	
			//g_shapeGravityApplied = true;

			D3DXVECTOR4 const forceDueToGravity = Empire::g_accelerationDueToGravity * shapePtr->mass();

			totalForce += forceDueToGravity;
		}

		if( Empire::g_inputActionArray[ Empire::force0InputAction ] ) // && ( shapeIndex != 0 ) )
		{		
			//g_shapeForce0Applied = true;
			
			D3DXVECTOR4 force0;
			D3DXVec4Transform( &force0, &Empire::g_force0LocalSpace, &shapePtr->dynamics().transformation() );

			totalForce += force0;

			D3DXVECTOR4 perpForce0ApplicationPositionLocalSpace;
			perpForce0ApplicationPositionLocalSpace[ 0 ] = -Empire::g_force0ApplicationPositionLocalSpace[ 1 ];
			perpForce0ApplicationPositionLocalSpace[ 1 ] = Empire::g_force0ApplicationPositionLocalSpace[ 0 ];
			perpForce0ApplicationPositionLocalSpace[ 2 ] = Empire::g_force0ApplicationPositionLocalSpace[ 2 ];
			perpForce0ApplicationPositionLocalSpace[ 3 ] = Empire::g_force0ApplicationPositionLocalSpace[ 3 ];
			
			float const torque0 =
				( perpForce0ApplicationPositionLocalSpace[ 0 ] * Empire::g_force0LocalSpace[ 0 ] ) + 
				( perpForce0ApplicationPositionLocalSpace[ 1 ] * Empire::g_force0LocalSpace[ 1 ] );

			totalTorque += torque0;
		}

		if( Empire::g_inputActionArray[ Empire::force1InputAction ] ) // && ( shapeIndex != 0 ) )
		{		
			//g_shapeForce1Applied = true;
			
			D3DXVECTOR4 force1;
			D3DXVec4Transform( &force1, &Empire::g_force1LocalSpace, &shapePtr->dynamics().transformation() );

			totalForce += force1;

			D3DXVECTOR4 perpForce1ApplicationPositionLocalSpace;
			perpForce1ApplicationPositionLocalSpace[ 0 ] = -Empire::g_force1ApplicationPositionLocalSpace[ 1 ];
			perpForce1ApplicationPositionLocalSpace[ 1 ] = Empire::g_force1ApplicationPositionLocalSpace[ 0 ];
			perpForce1ApplicationPositionLocalSpace[ 2 ] = Empire::g_force1ApplicationPositionLocalSpace[ 2 ];
			perpForce1ApplicationPositionLocalSpace[ 3 ] = Empire::g_force1ApplicationPositionLocalSpace[ 3 ];
			
			float const torque1 =
				( perpForce1ApplicationPositionLocalSpace[ 0 ] * Empire::g_force1LocalSpace[ 0 ] ) + 
				( perpForce1ApplicationPositionLocalSpace[ 1 ] * Empire::g_force1LocalSpace[ 1 ] );

			totalTorque += torque1;
		}

		shapePtr->setForce( totalForce );
		shapePtr->setTorque( totalTorque );

		//shapePtr->step( 
		//	totalForce, 
		//	totalTorque, 
		//	SECONDS_PER_FRAME,
		//	EMPIRE_NUMBER_OF_SHAPES,
		//	g_shapeArray );

	}
	#endif

	//{
	//	g_floorShape.step( 
	//		D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 0.0f ), 
	//		0.0f, // totalTorque, 
	//		SECONDS_PER_FRAME );
	//}

	//{
	//	for( ShapePairVectorClass::iterator shapePairItr = g_shapePairVector.begin(); shapePairItr != g_shapePairVector.end(); ++shapePairItr )
	//	{
	//		shapePairItr->step();
	//	}
	//}

	//assert( !Empire::g_physicsEngine.anyShapesInCollision() );
	Empire::g_physicsEngine.step( SECONDS_PER_FRAME );
	//if( Empire::g_physicsEngine.anyShapesInCollision() )
	//{
	//	Empire::g_physicsEngine = Empire::g_physicsDebug.engineDeque().back();
	//}
	//else
	{
		Empire::g_physicsDebug.step( Empire::g_physicsEngine, SECONDS_PER_FRAME );
	}

	DevGraphics::step( SECONDS_PER_FRAME );

	// Update the camera's position based on user input 
	g_Camera.FrameMove( fElapsedTime );

	for( int inputAction = 0; inputAction != Empire::numberOfInputActions; ++inputAction )
	{
		Empire::g_previousInputActionArray[ inputAction ] = Empire::g_inputActionArray[ inputAction ];
	}

}

//void renderFeatureConnection(
//	IDirect3DDevice9* pd3dDevice,
//	Physics::ShapeClass const & shapeA,
//	Physics::FeatureClass const & shapeAFeature,
//	float const shapeADistanceAlongEdge,
//	Physics::ShapeClass const & shapeB,
//	Physics::FeatureClass const & shapeBFeature,
//	float const shapeBDistanceAlongEdge )
//{
//	D3DXVECTOR4 fromPosition = shapeA.dynamics().position();	
//	switch( shapeAFeature.type() )
//	{
//	case Physics::VertexFeature :
//		{
//			fromPosition = shapeA.transformedVertex( shapeAFeature.index() );
//		}
//		break;
//
//	case Physics::EdgeFeature :
//	case Physics::FaceFeature :
//	case Physics::numberOfFeatures :
//	default :
//		{
//			fromPosition = 
//				shapeA.transformedVertex( shapeAFeature.index() ) +
//				( shapeA.transformedEdgeDirectionUnit( shapeAFeature.index() ) * shapeADistanceAlongEdge );
//				//( shapeA.transformedEdgeDirection( shapeAFeature.index() ) * 0.5f );
//		}
//		break;
//	}
//
//	D3DXVECTOR4 toPosition = shapeB.dynamics().position();
//	switch( shapeBFeature.type() )
//	{
//	case Physics::VertexFeature :
//		{
//			toPosition = shapeB.transformedVertex( shapeBFeature.index() );
//		}
//		break;
//
//	case Physics::EdgeFeature :
//	case Physics::FaceFeature :
//	case Physics::numberOfFeatures :
//	default :
//		{
//			toPosition = 
//				shapeB.transformedVertex( shapeBFeature.index() ) +
//				( shapeB.transformedEdgeDirectionUnit( shapeBFeature.index() ) * shapeBDistanceAlongEdge );
//				//( shapeB.transformedEdgeDirection( shapeBFeature.index() ) * 0.5f );
//		}
//		break;
//	}
//
//	CUSTOMVERTEX vertexArray[ 2 ];
//	vertexArray[ 0 ].x = fromPosition.x;
//	vertexArray[ 0 ].y = fromPosition.y;
//	vertexArray[ 0 ].z = fromPosition.z;
//	vertexArray[ 0 ].colour = D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	vertexArray[ 1 ].x = toPosition.x;
//	vertexArray[ 1 ].y = toPosition.y;
//	vertexArray[ 1 ].z = toPosition.z;
//	vertexArray[ 1 ].colour = D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//		
//	D3DXMATRIXA16 matWorld;
//	D3DXMatrixIdentity( &matWorld );
//	pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
//	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
//	pd3dDevice->DrawPrimitiveUP( 
//		D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
//		1, // UINT PrimitiveCount,
//		vertexArray, // CONST void* pVertexStreamZeroData,
//		sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
//}

//void renderShape(
//	IDirect3DDevice9* pd3dDevice,
//	Physics::ShapeClass const & shape,
//	//Physics::FeatureClass const & feature,
//	DWORD const colour )
//{
//	Physics::D3DXVECTOR4VectorType const & shapeVertexVector = shape.vertexVector();
//	unsigned int const numberOfShapeVertices = shapeVertexVector.size();
//	if( numberOfShapeVertices > 1 )
//	{ 
//		unsigned int const vertexArraySize = 16;
//		CUSTOMVERTEX frontVertexArray[ vertexArraySize ];
//		CUSTOMVERTEX rearVertexArray[ vertexArraySize ];
//		assert( ( numberOfShapeVertices * 2 ) <= vertexArraySize );
//		
//		frontVertexArray[ 0 ].x = shape.averageVertexPosition().x;
//		frontVertexArray[ 0 ].y = shape.averageVertexPosition().y;
//		frontVertexArray[ 0 ].z = shape.averageVertexPosition().z;
//		frontVertexArray[ 0 ].colour = D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//		rearVertexArray[ 0 ] = frontVertexArray[ 0 ];
//
//		for( unsigned int shapeVertexIndex = 0; shapeVertexIndex != numberOfShapeVertices; ++shapeVertexIndex )
//		{
//			frontVertexArray[ shapeVertexIndex + 1 ].x = shapeVertexVector[ shapeVertexIndex ].x;
//			frontVertexArray[ shapeVertexIndex + 1 ].y = shapeVertexVector[ shapeVertexIndex ].y;
//			frontVertexArray[ shapeVertexIndex + 1 ].z = 0.0f;
//			frontVertexArray[ shapeVertexIndex + 1 ].colour = colour; // D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f );	
//			rearVertexArray[ shapeVertexIndex + 1 ].x = shapeVertexVector[ numberOfShapeVertices - ( shapeVertexIndex + 1 ) ].x;
//			rearVertexArray[ shapeVertexIndex + 1 ].y = shapeVertexVector[ numberOfShapeVertices - ( shapeVertexIndex + 1 ) ].y;
//			rearVertexArray[ shapeVertexIndex + 1 ].z = 0.0f;
//			rearVertexArray[ shapeVertexIndex + 1 ].colour = colour; // D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f );			
//		}
//
//		frontVertexArray[ numberOfShapeVertices + 1 ].x = shapeVertexVector[ 0 ].x;
//		frontVertexArray[ numberOfShapeVertices + 1 ].y = shapeVertexVector[ 0 ].y;
//		frontVertexArray[ numberOfShapeVertices + 1 ].z = 0.0f;
//		frontVertexArray[ numberOfShapeVertices + 1 ].colour = colour; // D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f );	
//		rearVertexArray[ numberOfShapeVertices + 1 ].x = shapeVertexVector[ numberOfShapeVertices - 1 ].x;
//		rearVertexArray[ numberOfShapeVertices + 1 ].y = shapeVertexVector[ numberOfShapeVertices - 1 ].y;
//		rearVertexArray[ numberOfShapeVertices + 1 ].z = 0.0f;
//		rearVertexArray[ numberOfShapeVertices + 1 ].colour = colour; // D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f );	
//					
//		pd3dDevice->SetTransform( D3DTS_WORLD, &( shape.dynamics().transformation() ) );
//		pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
//		pd3dDevice->DrawPrimitiveUP( 
//			D3DPT_TRIANGLEFAN, // D3DPRIMITIVETYPE PrimitiveType,
//			numberOfShapeVertices, // UINT PrimitiveCount,
//			frontVertexArray, // CONST void* pVertexStreamZeroData,
//			sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
//		pd3dDevice->DrawPrimitiveUP( 
//			D3DPT_TRIANGLEFAN, // D3DPRIMITIVETYPE PrimitiveType,
//			numberOfShapeVertices, // UINT PrimitiveCount,
//			rearVertexArray, // CONST void* pVertexStreamZeroData,
//			sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
//	}
//
//	//#if 1
//	//// Feature
//	//{
//	//	CUSTOMVERTEX vertexArray[ 2 ];
//	//	float const edgeLineLength = 3.0f;	
//	//	
//	//	D3DXMATRIXA16 matWorld;
//	//	D3DXMatrixIdentity( &matWorld );
//	//	pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
//	//	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
//	//	
//	//	DWORD const colourArray[ ] =
//	//	{
//	//		D3DCOLOR_COLORVALUE( 0.0f, 0.0f, 1.0f, 1.0f ), // Physics::VClipDone,
//	//		D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f ), // Physics::VClipContinue,
//	//		D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f ), // Physics::VClipPenetration
//	//	};
//
//	//	switch( feature.type() )
//	//	{
//	//	case Physics::VertexFeature :
//	//		{
//	//			unsigned int const vertexIndex = feature.index();
//	//			unsigned int const edgeIndex = feature.index();
//	//			unsigned int const previousEdgeIndex = ( ( feature.index() == 0 ) ? ( shape.vertexVector().size() - 1 ) : ( feature.index() - 1 ) );
//	//			
//	//			D3DXVECTOR4 const shapeTransformedVertex = shape.transformedVertex( vertexIndex );
//	//			D3DXVECTOR4 const shapeTransformedEdgeNormalDirectionUnit = shape.transformedEdgeNormalDirectionUnit( edgeIndex );
//	//			D3DXVECTOR4 const shapeTransformedPreviousEdgeNormalDirectionUnit = shape.transformedEdgeNormalDirectionUnit( previousEdgeIndex );
//
//	//			vertexArray[ 0 ].x = shapeTransformedVertex.x;
//	//			vertexArray[ 0 ].y = shapeTransformedVertex.y;
//	//			vertexArray[ 0 ].z = shapeTransformedVertex.z;
//	//			vertexArray[ 0 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//			vertexArray[ 1 ].x = shapeTransformedVertex.x + ( shapeTransformedEdgeNormalDirectionUnit.x * edgeLineLength );
//	//			vertexArray[ 1 ].y = shapeTransformedVertex.y + ( shapeTransformedEdgeNormalDirectionUnit.y * edgeLineLength );
//	//			vertexArray[ 1 ].z = shapeTransformedVertex.z + ( shapeTransformedEdgeNormalDirectionUnit.z * edgeLineLength );
//	//			vertexArray[ 1 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//				
//	//			pd3dDevice->DrawPrimitiveUP( 
//	//				D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
//	//				1, // UINT PrimitiveCount,
//	//				vertexArray, // CONST void* pVertexStreamZeroData,
//	//				sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
//	//				
//	//			vertexArray[ 0 ].x = shapeTransformedVertex.x;
//	//			vertexArray[ 0 ].y = shapeTransformedVertex.y;
//	//			vertexArray[ 0 ].z = shapeTransformedVertex.z;
//	//			vertexArray[ 0 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//			vertexArray[ 1 ].x = shapeTransformedVertex.x + ( shapeTransformedPreviousEdgeNormalDirectionUnit.x * edgeLineLength );
//	//			vertexArray[ 1 ].y = shapeTransformedVertex.y + ( shapeTransformedPreviousEdgeNormalDirectionUnit.y * edgeLineLength );
//	//			vertexArray[ 1 ].z = shapeTransformedVertex.z + ( shapeTransformedPreviousEdgeNormalDirectionUnit.z * edgeLineLength );
//	//			vertexArray[ 1 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//				
//	//			pd3dDevice->DrawPrimitiveUP( 
//	//				D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
//	//				1, // UINT PrimitiveCount,
//	//				vertexArray, // CONST void* pVertexStreamZeroData,
//	//				sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride				
//	//		}
//	//		break;
//
//	//	case Physics::EdgeFeature :
//	//	case Physics::FaceFeature :
//	//	case Physics::numberOfFeatures :
//	//	default :
//	//		{
//	//			unsigned int const edgeIndex = feature.index();
//	//			unsigned int const tailVertexIndex = feature.index();
//	//			unsigned int const headVertexIndex = ( ( feature.index() == ( shape.vertexVector().size() - 1 ) ) ? 0 : ( feature.index() + 1 ) );
//	//			
//	//			D3DXVECTOR4 const shapeTransformedTailVertex = shape.transformedVertex( tailVertexIndex );
//	//			D3DXVECTOR4 const shapeTransformedHeadVertex = shape.transformedVertex( headVertexIndex );
//	//			D3DXVECTOR4 const shapeTransformedEdgeNormalDirectionUnit = shape.transformedEdgeNormalDirectionUnit( edgeIndex );
//
//	//			vertexArray[ 0 ].x = shapeTransformedTailVertex.x;
//	//			vertexArray[ 0 ].y = shapeTransformedTailVertex.y;
//	//			vertexArray[ 0 ].z = shapeTransformedTailVertex.z;
//	//			vertexArray[ 0 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//			vertexArray[ 1 ].x = shapeTransformedTailVertex.x + ( shapeTransformedEdgeNormalDirectionUnit.x * edgeLineLength );
//	//			vertexArray[ 1 ].y = shapeTransformedTailVertex.y + ( shapeTransformedEdgeNormalDirectionUnit.y * edgeLineLength );
//	//			vertexArray[ 1 ].z = shapeTransformedTailVertex.z + ( shapeTransformedEdgeNormalDirectionUnit.z * edgeLineLength );
//	//			vertexArray[ 1 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//				
//	//			pd3dDevice->DrawPrimitiveUP( 
//	//				D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
//	//				1, // UINT PrimitiveCount,
//	//				vertexArray, // CONST void* pVertexStreamZeroData,
//	//				sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
//	//				
//	//			vertexArray[ 0 ].x = shapeTransformedHeadVertex.x;
//	//			vertexArray[ 0 ].y = shapeTransformedHeadVertex.y;
//	//			vertexArray[ 0 ].z = shapeTransformedHeadVertex.z;
//	//			vertexArray[ 0 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//			vertexArray[ 1 ].x = shapeTransformedHeadVertex.x + ( shapeTransformedEdgeNormalDirectionUnit.x * edgeLineLength );
//	//			vertexArray[ 1 ].y = shapeTransformedHeadVertex.y + ( shapeTransformedEdgeNormalDirectionUnit.y * edgeLineLength );
//	//			vertexArray[ 1 ].z = shapeTransformedHeadVertex.z + ( shapeTransformedEdgeNormalDirectionUnit.z * edgeLineLength );
//	//			vertexArray[ 1 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//				
//	//			pd3dDevice->DrawPrimitiveUP( 
//	//				D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
//	//				1, // UINT PrimitiveCount,
//	//				vertexArray, // CONST void* pVertexStreamZeroData,
//	//				sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride				
//	//				
//	//			vertexArray[ 0 ].x = shapeTransformedTailVertex.x;
//	//			vertexArray[ 0 ].y = shapeTransformedTailVertex.y;
//	//			vertexArray[ 0 ].z = shapeTransformedTailVertex.z;
//	//			vertexArray[ 0 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//			vertexArray[ 1 ].x = shapeTransformedHeadVertex.x;
//	//			vertexArray[ 1 ].y = shapeTransformedHeadVertex.y;
//	//			vertexArray[ 1 ].z = shapeTransformedHeadVertex.z;
//	//			vertexArray[ 1 ].colour = colourArray[ g_VClipState ]; // D3DCOLOR_COLORVALUE( 1.0f, 1.0f, 1.0f, 1.0f );
//	//				
//	//			pd3dDevice->DrawPrimitiveUP( 
//	//				D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
//	//				1, // UINT PrimitiveCount,
//	//				vertexArray, // CONST void* pVertexStreamZeroData,
//	//				sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride				
//	//		}
//	//		break;
//	//	}
//	//}
//	//#endif
//}

//bool shapeInCollision( Physics::ShapeClass const & shape )
//{
//	for( unsigned int shapeIndex = 0; shapeIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
//	{
//		if( &shape != &g_shapeArray[ shapeIndex ] )
//		{
//			if( shapeCollision( shape, g_shapeArray[ shapeIndex ] ) )
//			{
//				return true;
//			}
//		}
//	}
//
//	//if( &shape != &g_floorShape )
//	//{
//	//	if( shapeCollision( shape, g_floorShape ) )
//	//	{
//	//		return true;
//	//	}
//	//}
//
//	return false;
//}

//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
	HRESULT hr;
    D3DXMATRIXA16 mWorld;
    D3DXMATRIXA16 mView;
    D3DXMATRIXA16 mProj;
    D3DXMATRIXA16 mWorldViewProjection;

    // If the settings dialog is being shown, then render it instead of rendering the app's scene
    if( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.OnRender( fElapsedTime );
        return;
    }

    // Clear the render target and the zbuffer 
    V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0, 45, 50, 170 ), 1.0f, 0 ) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
        // Get the projection & view matrix from the camera class
		D3DXMatrixIdentity( &mWorld );
        mProj = *g_Camera.GetProjMatrix();
        mView = *g_Camera.GetViewMatrix();

        mWorldViewProjection = mWorld * mView * mProj;

		pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );


		// Set up our view matrix. A view matrix can be defined given an eye point,
		// a point to lookat, and a direction for which way is up. Here, we set the
		// eye five units back along the z-axis and up three units, look at the 
		// origin, and define "up" to be in the y-direction.
		D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-50.0f );
		D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
		D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
		D3DXMATRIXA16 matView;
		D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
		pd3dDevice->SetTransform( D3DTS_VIEW, &mView );

		// For the projection matrix, we set up a perspective transform (which
		// transforms geometry from 3D view space to 2D viewport space, with
		// a perspective divide making objects smaller in the distance). To build
		// a perpsective transform, we need the field of view (1/4 pi is common),
		// the aspect ratio, and the near and far clipping planes (which define at
		// what distances geometry should be no longer be rendered).
		D3DXMATRIXA16 matProj;
		D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
		pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

		Empire::g_physicsEngine.draw( *pd3dDevice );
		Empire::g_physicsDebug.draw( *pd3dDevice, Empire::g_physicsEngine );

		DevGraphics::draw( *pd3dDevice );
		
		////DWORD const shapeColour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//for( unsigned int shapeIndex = 0; shapeIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
		//{
		//	DWORD const shapeColour = 
		//		( shapeInCollision( g_shapeArray[ shapeIndex ] ) ? 
		//			( D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f ) ) :
		//			( D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f ) ) );
		//
		//	renderShape( 
		//		pd3dDevice, 
		//		g_shapeArray[ shapeIndex ], 
		//		//g_featureArray[ shapeIndex ], 
		//		shapeColour );
		//}

		//DWORD const floorShapeColour = 
		//	( shapeInCollision( g_floorShape ) ? 
		//		( D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f ) ) :
		//		( D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f ) ) );		
		////DWORD const floorShapeColour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//renderShape(
		//	pd3dDevice, 
		//	g_floorShape,
		//	//g_floorfeature, 
		//	floorShapeColour );

		//{
		//	for( unsigned int shapeIndex = 1; shapeIndex < EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
		//	{
		//		Physics::FeatureClass shapeAFeature;
		//		float shapeADistanceAlongEdge = 0.0f;
		//		Physics::FeatureClass shapeBFeature;
		//		float shapeBDistanceAlongEdge = 0.0f;
		//		
		//		shapeClosestFeatures(
		//			g_shapeArray[ 0 ], shapeAFeature, shapeADistanceAlongEdge,					
		//			g_shapeArray[ shapeIndex ], shapeBFeature, shapeBDistanceAlongEdge );

		//		renderFeatureConnection( 
		//			pd3dDevice, 
		//			g_shapeArray[ 0 ], shapeAFeature, shapeADistanceAlongEdge,
		//			g_shapeArray[ shapeIndex ], shapeBFeature, shapeBDistanceAlongEdge );
		//	}
		//}

		// Draw some lines
		//if( g_shapeGravityApplied )
		//{
		//	//D3DXMATRIX const boxTransformation = g_shape.transformation();
		//	//D3DXVECTOR4 const boxPosition = boxTransformation.m[ 3 ];
		//	D3DXVECTOR4 const boxPosition = g_shapeArray[ 0 ].centerOfMassWorldPosition();

		//	D3DXVECTOR4 const boxForceDueToGravity = Empire::g_accelerationDueToGravity * g_shapeArray[ 0 ].mass() * 10.0f;

		//	CUSTOMVERTEX vertexArray[ 2 ];
		//	vertexArray[ 0 ].x = boxPosition[ 0 ];
		//	vertexArray[ 0 ].y = boxPosition[ 1 ];
		//	vertexArray[ 0 ].z = boxPosition[ 2 ];
		//	vertexArray[ 0 ].colour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//	vertexArray[ 1 ].x = boxPosition[ 0 ] - ( boxForceDueToGravity[ 0 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].y = boxPosition[ 1 ] - ( boxForceDueToGravity[ 1 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].z = boxPosition[ 2 ] - ( boxForceDueToGravity[ 2 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].colour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//				
		//	//D3DXMatrixIdentity( &matWorld );
		//	pd3dDevice->SetTransform( D3DTS_WORLD, &mWorld );
		//	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		//	pd3dDevice->DrawPrimitiveUP( 
		//		D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
		//		1, // UINT PrimitiveCount,
		//		vertexArray, // CONST void* pVertexStreamZeroData,
		//		sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
		//}
			
		//if( g_shapeForce0Applied )
		//{
		//	CUSTOMVERTEX vertexArray[ 2 ];
		//	vertexArray[ 0 ].x = Empire::g_force0ApplicationPositionLocalSpace[ 0 ];
		//	vertexArray[ 0 ].y = Empire::g_force0ApplicationPositionLocalSpace[ 1 ];
		//	vertexArray[ 0 ].z = Empire::g_force0ApplicationPositionLocalSpace[ 2 ];
		//	vertexArray[ 0 ].colour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//	vertexArray[ 1 ].x = Empire::g_force0ApplicationPositionLocalSpace[ 0 ] - ( Empire::g_force0LocalSpace[ 0 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].y = Empire::g_force0ApplicationPositionLocalSpace[ 1 ] - ( Empire::g_force0LocalSpace[ 1 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].z = Empire::g_force0ApplicationPositionLocalSpace[ 2 ] - ( Empire::g_force0LocalSpace[ 2 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].colour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//				
		//	pd3dDevice->SetTransform( D3DTS_WORLD, &( g_shapeArray[ 0 ].dynamics().transformation() ) );
		//	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		//	pd3dDevice->DrawPrimitiveUP( 
		//		D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
		//		1, // UINT PrimitiveCount,
		//		vertexArray, // CONST void* pVertexStreamZeroData,
		//		sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
		//}
		//			
		//if( g_shapeForce1Applied )
		//{
		//	CUSTOMVERTEX vertexArray[ 2 ];
		//	vertexArray[ 0 ].x = Empire::g_force1ApplicationPositionLocalSpace[ 0 ];
		//	vertexArray[ 0 ].y = Empire::g_force1ApplicationPositionLocalSpace[ 1 ];
		//	vertexArray[ 0 ].z = Empire::g_force1ApplicationPositionLocalSpace[ 2 ];
		//	vertexArray[ 0 ].colour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//	vertexArray[ 1 ].x = Empire::g_force1ApplicationPositionLocalSpace[ 0 ] - ( Empire::g_force1LocalSpace[ 0 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].y = Empire::g_force1ApplicationPositionLocalSpace[ 1 ] - ( Empire::g_force1LocalSpace[ 1 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].z = Empire::g_force1ApplicationPositionLocalSpace[ 2 ] - ( Empire::g_force1LocalSpace[ 2 ] * EMPIRE_FORCE_LINE_SCALE );
		//	vertexArray[ 1 ].colour = D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f );
		//				
		//	pd3dDevice->SetTransform( D3DTS_WORLD, &( g_shapeArray[ 0 ].dynamics().transformation() ) );
		//	pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		//	pd3dDevice->DrawPrimitiveUP( 
		//		D3DPT_LINELIST, // D3DPRIMITIVETYPE PrimitiveType,
		//		1, // UINT PrimitiveCount,
		//		vertexArray, // CONST void* pVertexStreamZeroData,
		//		sizeof( CUSTOMVERTEX ) ); // UINT VertexStreamZeroStride
		//}		

        // Update the effect's variables.  Instead of using strings, it would 
        // be more efficient to cache a handle to the parameter by calling 
        // ID3DXEffect::GetParameterByName
		D3DXHANDLE worldViewProjectionHandle = g_pEffect9->GetParameterByName(0, "g_mWorldViewProjection");
        V( g_pEffect9->SetMatrix( worldViewProjectionHandle, &mWorldViewProjection ) );
		D3DXHANDLE worldHandle = g_pEffect9->GetParameterByName(0, "g_mWorld");
        V( g_pEffect9->SetMatrix( worldHandle, &mWorld ) );
		D3DXHANDLE timeHandle = g_pEffect9->GetParameterByName(0, "g_fTime");
        V( g_pEffect9->SetFloat( timeHandle, ( float )fTime ) );
        //V( g_pEffect9->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) );
        //V( g_pEffect9->SetMatrix( "g_mWorld", &mWorld ) );
        //V( g_pEffect9->SetFloat( "g_fTime", ( float )fTime ) );



        DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" ); // These events are to help PIX identify what the code is doing
       // RenderText( matWorld, matView, matProj );
        RenderText( mWorld, mView, mProj );
        V( g_HUD.OnRender( fElapsedTime ) );
        V( g_SampleUI.OnRender( fElapsedTime ) );
        DXUT_EndPerfEvent();

        V( pd3dDevice->EndScene() );
    }
}

//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
                          void* pUserContext )
{
    // Pass messages to dialog resource manager calls so GUI state is updated correctly
    *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass messages to settings dialog if its active
    if( g_SettingsDlg.IsActive() )
    {
        g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        return 0;
    }

    // Give the dialogs a chance to handle the message first
    *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;
    *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass all remaining windows messages to camera so it can respond to user input
    g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );

	// Do my own message handling	
    switch( uMsg )
    {
        case WM_KEYDOWN:
        {
			Empire::InputActionEnum const empireInputAction = Empire::mapKeyToInputAction( ( UINT )wParam );
			if( empireInputAction != Empire::numberOfInputActions )
            {
				Empire::g_inputActionArray[ empireInputAction ] = true;
            }
        }
        break;

        case WM_KEYUP:
        {
			Empire::InputActionEnum const empireInputAction = Empire::mapKeyToInputAction( ( UINT )wParam );
			if( empireInputAction != Empire::numberOfInputActions )
            {
				Empire::g_inputActionArray[ empireInputAction ] = false;
            }
        }
        break;

        case WM_RBUTTONDOWN:
        case WM_MBUTTONDOWN:
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDBLCLK:
        case WM_MBUTTONDBLCLK:
        case WM_LBUTTONDBLCLK:
            {
                // Compute the drag rectangle in screen coord.
                POINT ptCursor = { ( short )LOWORD( lParam ), ( short )HIWORD( lParam ) };

                // Update member var state
                if( ( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK ) ) // && PtInRect( &g_rcDrag, ptCursor ) )
                {
                    g_bMouseLButtonDown = true; g_nCurrentButtonMask |= MOUSE_LEFT_BUTTON;
                }
                if( ( uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONDBLCLK ) ) // && PtInRect( &g_rcDrag, ptCursor ) )
                {
                    g_bMouseMButtonDown = true; g_nCurrentButtonMask |= MOUSE_MIDDLE_BUTTON;
                }
                if( ( uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONDBLCLK ) ) // && PtInRect( &g_rcDrag, ptCursor ) )
                {
                    g_bMouseRButtonDown = true; g_nCurrentButtonMask |= MOUSE_RIGHT_BUTTON;
                }			

                // Capture the mouse, so if the mouse button is 
                // released outside the window, we'll get the WM_LBUTTONUP message
                SetCapture( hWnd );
                GetCursorPos( &g_ptLastMousePosition );
				g_ptLastMousePosition = ptCursor;
                return TRUE;
            }
			break;

        case WM_RBUTTONUP:
        case WM_MBUTTONUP:
        case WM_LBUTTONUP:
            {
                // Update member var state
                if( uMsg == WM_LBUTTONUP )
                {
                    g_bMouseLButtonDown = false; g_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON;
                }
                if( uMsg == WM_MBUTTONUP )
                {
                    g_bMouseMButtonDown = false; g_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON;
                }
                if( uMsg == WM_RBUTTONUP )
                {
                    g_bMouseRButtonDown = false; g_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON;
                }

                // Release the capture if no mouse buttons down
                if( !g_bMouseLButtonDown &&
                    !g_bMouseRButtonDown &&
                    !g_bMouseMButtonDown )
                {
                    ReleaseCapture();
                }
            }
            break;

        case WM_CAPTURECHANGED:
        {
            if( ( HWND )lParam != hWnd )
            {
                if( ( g_nCurrentButtonMask & MOUSE_LEFT_BUTTON ) ||
                    ( g_nCurrentButtonMask & MOUSE_MIDDLE_BUTTON ) ||
                    ( g_nCurrentButtonMask & MOUSE_RIGHT_BUTTON ) )
                {
                    g_bMouseLButtonDown = false;
                    g_bMouseMButtonDown = false;
                    g_bMouseRButtonDown = false;
                    g_nCurrentButtonMask &= ~MOUSE_LEFT_BUTTON;
                    g_nCurrentButtonMask &= ~MOUSE_MIDDLE_BUTTON;
                    g_nCurrentButtonMask &= ~MOUSE_RIGHT_BUTTON;
                    ReleaseCapture();
                }
            }
        }
        break;

        case WM_MOUSEWHEEL:
			{
				// Update member var state
	            g_nMouseWheelDelta += ( short )HIWORD( wParam );
			}
			break;
    }

    return 0;
}


//--------------------------------------------------------------------------------------
// Handle key presses
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Handles the GUI events
//--------------------------------------------------------------------------------------
void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext )
{
    switch( nControlID )
    {
        case IDC_TOGGLEFULLSCREEN:
            DXUTToggleFullScreen(); break;
        case IDC_TOGGLEREF:
            DXUTToggleREF(); break;
        case IDC_CHANGEDEVICE:
            g_SettingsDlg.SetActive( !g_SettingsDlg.IsActive() ); break;
    }
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9LostDevice( void* pUserContext )
{
    g_DialogResourceManager.OnD3D9LostDevice();
    g_SettingsDlg.OnD3D9LostDevice();
    if( g_pFont9 ) g_pFont9->OnLostDevice();
    if( g_pEffect9 ) g_pEffect9->OnLostDevice();
    SAFE_RELEASE( g_pSprite9 );
    SAFE_DELETE( g_pTxtHelper );
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{	
	#if HARDCODED_SHAPES_ON
	for( unsigned int shapeIndex = 0; shapeIndex != EMPIRE_NUMBER_OF_SHAPES; ++shapeIndex )
	{
		Empire::g_physicsEngine.destroyShape( g_shapeUIDArray[ shapeIndex ] );
	}
	#endif

	for( unsigned int XMLShapeIndex = 0; XMLShapeIndex != EMPIRE_NUMBER_OF_XML_SHAPES; ++XMLShapeIndex )
	{
		if( g_XMLShapeUIDArray[ XMLShapeIndex ] != PHYSICS_SHAPE_NULL_UID )
		{
			Empire::g_physicsEngine.destroyShape( g_XMLShapeUIDArray[ XMLShapeIndex ] );
			g_XMLShapeUIDArray[ XMLShapeIndex ] = PHYSICS_SHAPE_NULL_UID;
		}
	}

	Empire::shutdown();

    g_DialogResourceManager.OnD3D9DestroyDevice();
    g_SettingsDlg.OnD3D9DestroyDevice();
    SAFE_RELEASE( g_pEffect9 );
    SAFE_RELEASE( g_pFont9 );
}

